package com.gamefx.resource
{
	import com.gamefx.resource.events.LoaderEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.utils.getQualifiedClassName;

	[Event(name="open", 			type="flash.events.Event")]
	[Event(name="progress", 		type="flash.events.Event")]
	[Event(name="complete", 		type="flash.events.Event")]
	[Event(name="httpStatus", 	type="flash.events.Event")]
	[Event(name="cancel",			type="com.gamefx.resource.events.LoaderEvent")]
	[Event(name="fail", 			type="com.gamefx.resource.events.LoaderEvent")]
	

	public class LoaderItem extends EventDispatcher
	{
		protected static var _isLocal:Boolean;
		
		public var url:String;
		public var request:URLRequest;
		public var priority:uint;
		public var estimatedBytes:uint;
		

		protected var status:int;



		public function LoaderItem(urlOrRequest:*, priority:uint=1, estimatedBytes:uint=0)
		{
			if (getQualifiedClassName(this) == "com.gamefx.resource::LoaderItem")
			{
				throw new Error("LoaderItem can't instantiation, can only be inherited.");
			}

			request = (urlOrRequest is URLRequest) ? urlOrRequest as URLRequest : new URLRequest(urlOrRequest);
			url = request.url;
			this.priority = priority;
			this.estimatedBytes = (estimatedBytes != 0) ? estimatedBytes : LoaderManager.defaultEstimatedBytes;
			
			_bytesTotal = this.estimatedBytes;
		}

		//--------------------------------------------------------------------------
		//
		//  Properties
		//
		//--------------------------------------------------------------------------
		/**
		 *
		 */
		protected var _bytesTotal:uint;

		public function get bytesTotal():uint
		{
			return _bytesTotal;
		}

		/**
		 *
		 */
		protected var _bytesLoaded:uint;

		public function get bytesLoaded():uint
		{
			return _bytesLoaded;
		}

		/**
		 *
		 */
		protected var _ownerLoader:LoaderGroup;

		internal function get ownerLoader():LoaderGroup
		{
			return _ownerLoader;
		}

		internal function set ownerLoader(loader:LoaderGroup):void
		{
			_ownerLoader = loader;
		}

		/**
		 *
		 */
		protected var _index:int;

		internal function get index():int
		{
			return _index;
		}

		internal function set index(value:int):void
		{
			_index = value;
			status = LoaderStatus.LOADING;
		}


		//--------------------------------------------------------------------------
		//
		//  Methods
		//
		//--------------------------------------------------------------------------

		public function load():void
		{
			if (status == LoaderStatus.LOADING)
			{
				return;
			}

			if (_ownerLoader != null && status != LoaderStatus.PAUSED)
			{
				return;
			}

			LoaderManager.append(this);
		}

		public function cancel():void
		{
			dispatchEvent(new LoaderEvent(LoaderEvent.CANCEL, this));
			status = LoaderStatus.PAUSED;

			if (_ownerLoader != null)
			{
				_ownerLoader.onChildCancel(this);
			}
		}


		//--------------------------------------------------------------------------

		internal function onOpen(event:Event):void
		{
			dispatchEvent(event)

			if (_ownerLoader != null)
			{
				_ownerLoader.onChildOpen(this);
			}
		}
		
		internal function onProgress(event:ProgressEvent):void
		{
			dispatchEvent(event)
			
			if (event.bytesTotal != _bytesTotal)
			{
				auditBytesTotal(event.bytesTotal - _bytesTotal);
			}
			
			if (event.bytesLoaded > event.bytesTotal)
			{
				auditBytesTotal(event.bytesLoaded - event.bytesTotal);
			}
			
			if (_ownerLoader != null)
			{
				_ownerLoader.onChildProgress(event.bytesLoaded - _bytesLoaded);
			}
			
			_bytesLoaded = event.bytesLoaded;
		}

		internal function onComplete(event:Event):void
		{
			dispatchEvent(event)

			if (_ownerLoader != null)
			{
				_ownerLoader.onChildComplete(this);
				_ownerLoader = null;
			}
		}

		internal function onHTTPStatus(event:HTTPStatusEvent):void
		{
			dispatchEvent(event)
		}

		internal function onIOError(event:IOErrorEvent):void
		{
			trace(event.text);
			dispatchEvent(new LoaderEvent(LoaderEvent.FAIL, event.currentTarget as LoaderItem, event.text))

			if (_ownerLoader != null)
			{
				_ownerLoader.onChildError(this);
			}
		}

		internal function onSecurityError(event:SecurityErrorEvent):void
		{
			trace(event.text);
			dispatchEvent(new LoaderEvent(LoaderEvent.FAIL, event.currentTarget as LoaderItem, event.text))

			if (_ownerLoader != null)
			{
				_ownerLoader.onChildError(this);
			}
		}


		//--------------------------------------------------------------------------

		internal function auditBytesTotal(bytesAudited:int):void
		{
			_bytesTotal += bytesAudited;

			if (_ownerLoader != null)
			{
				_ownerLoader.auditBytesTotal(bytesAudited);
			}
		}


	}
}
